package com.xinsoft.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinsoft.common.exception.BDException;
import com.xinsoft.constant.Const;
import com.xinsoft.entity.dto.MesProcessPlanDTO;
import com.xinsoft.entity.dto.QuaMaterialInspectionDTO;
import com.xinsoft.entity.dto.QuaMaterialInspectionParam;
import com.xinsoft.entity.dto.SysCountDTO;
import com.xinsoft.entity.po.*;
import com.xinsoft.service.*;
import com.xinsoft.mapper.QuaMaterialInspectionMapper;
import com.xinsoft.utils.TokenUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author hsm
* @description 针对表【qua_material_inspection(质量检验)】的数据库操作Service实现
* @createDate 2023-08-14 17:13:36
*/
@Service
public class QuaMaterialInspectionServiceImpl extends ServiceImpl<QuaMaterialInspectionMapper, QuaMaterialInspection>
    implements QuaMaterialInspectionService{

    @Resource
    QuaDocumentService documentService;
    @Resource
    private SysFileHisService sysFileHisService;
    @Resource
    private QuaMaterialInspectionDetailService quaMaterialInspectionDetailService;

    @Autowired
    private SysDocumentNumService sysDocumentNumService;

    @Autowired
    private MesProcessPlanDetailService mesProcessPlanDetailService;

    @Autowired
    private MesProcessPlanService mesProcessPlanService;

    @Autowired
    private SysMaterialService sysMaterialService;
    @Autowired
    private MesDispatchService mesDispatchService;

    @Autowired
    private QuaPlanCheckRefService planCheckRefService;

    @Autowired
    private QuaCheckItemService quaCheckItemService;

    @Autowired
    private MesFlowCardRuleRecordService flowCardRuleRecordService;


    @Override
    public IPage<QuaMaterialInspectionDTO> findPageListByParam(QuaMaterialInspectionParam param) {
        //分页
        Page<QuaMaterialInspectionDTO> page = new Page<QuaMaterialInspectionDTO>(param.getCurrentPage(), param.getPageSize());
        IPage<QuaMaterialInspectionDTO> resultPage = this.baseMapper.findListByParam(page, param);
        //返回值
        return resultPage;
    }

    @Override
    public QuaMaterialInspection addQuaMaterialInspection(QuaMaterialInspectionDTO quaMaterialInspectionDTO) {

        //判断编号否重复
        QueryWrapper<QuaMaterialInspection> codeQuery = new QueryWrapper<>();
        codeQuery.select("id");
        codeQuery.eq("inspection_no",quaMaterialInspectionDTO.getInspectionNo());
        List codes = this.list(codeQuery);
        if(CollectionUtil.isNotEmpty(codes)) {
            throw new BDException("操作失败，检验单编号重复！");
        }

        QuaMaterialInspection quaMaterialInspection = new QuaMaterialInspection();
        BeanUtils.copyProperties(quaMaterialInspectionDTO,quaMaterialInspection);

        quaMaterialInspection.setStatus(0);
        quaMaterialInspection.setAuditor(null);
        save(quaMaterialInspection);

        //保存明细行
        if(CollectionUtil.isNotEmpty(quaMaterialInspectionDTO.getQuaMaterialInspectionDetailList())){
            for (QuaMaterialInspectionDetail quaMaterialInspectionDetail : quaMaterialInspectionDTO.getQuaMaterialInspectionDetailList()) {
                quaMaterialInspectionDetail.setMaterialInspectionId(quaMaterialInspection.getId());
            }
            quaMaterialInspectionDetailService.saveBatch(quaMaterialInspectionDTO.getQuaMaterialInspectionDetailList());
        }

        //保存图片
        if(CollectionUtil.isNotEmpty(quaMaterialInspectionDTO.getSysFileHisList())){
            List<QuaDocument> quaDocumentList = new ArrayList<>();
            for (SysFileHis sysFileHis : quaMaterialInspectionDTO.getSysFileHisList()) {

                QuaDocument quaDocument = new QuaDocument();
                quaDocument.setQuaId(quaMaterialInspection.getId());
                quaDocument.setDocumentId(sysFileHis.getId());
                quaDocument.setQuaType(Const.DOCUMENT_QUA_TYPE.QUA_INSPECTION);
                quaDocumentList.add(quaDocument);
            }

            documentService.saveBatch(quaDocumentList);
        }
        return quaMaterialInspection;

    }

    /**
     * 编辑
     * @param quaMaterialInspectionDTO
     * @return
     */
    @Override
    public QuaMaterialInspection editQuaMaterialInspection(QuaMaterialInspectionDTO quaMaterialInspectionDTO) {

        QuaMaterialInspection quaMaterialInspection = new QuaMaterialInspection();
        BeanUtils.copyProperties(quaMaterialInspectionDTO,quaMaterialInspection);

        QuaMaterialInspection entity = getById(quaMaterialInspectionDTO.getId());
        if(Objects.equals(entity.getStatus(),1)){
            throw new BDException("操作失败，已检验无法编辑！");
        }

        quaMaterialInspection.setStatus(0);
        quaMaterialInspection.setInspector(null);
        updateById(quaMaterialInspection);

        // 更新检验项目，以及文件
        updateQuaMaterialDetail(quaMaterialInspectionDTO);

        return quaMaterialInspection;
    }

    /**
     * 提交检验
     * @param quaMaterialInspectionDTO
     * @return
     */
    @Override
    public QuaMaterialInspection commitInspection(QuaMaterialInspectionDTO quaMaterialInspectionDTO) {

        QuaMaterialInspection quaMaterialInspection = new QuaMaterialInspection();
        BeanUtils.copyProperties(quaMaterialInspectionDTO,quaMaterialInspection);
        QuaMaterialInspection entity = getById(quaMaterialInspectionDTO.getId());
        if(Objects.equals(entity.getStatus(),1)){
            throw new BDException("操作失败，已检验无法重复检验！");
        }
        quaMaterialInspection.setStatus(1);
        quaMaterialInspection.setInspector(TokenUtil.getUserId());
        updateById(quaMaterialInspection);

        // 更新检验项目，以及文件
        updateQuaMaterialDetail(quaMaterialInspectionDTO);

        // 如果是首样检验，则更新对应的工序计划为已完成首检
        if(Objects.equals(entity.getInspectionType(),Const.QUA_TYPE.QUA_SYJY)){
            MesProcessPlan mesProcessPlan = new MesProcessPlan();
            mesProcessPlan.setId(entity.getSourceId());
            mesProcessPlan.setDoFirstInspection(1);
            mesProcessPlanService.updateById(mesProcessPlan);
        }

        return quaMaterialInspection;
    }

    /**
     *更新检验项目，以及文件
     * @param quaMaterialInspectionDTO
     */
    private void updateQuaMaterialDetail(QuaMaterialInspectionDTO quaMaterialInspectionDTO) {

        //删除明细行
        QueryWrapper<QuaMaterialInspectionDetail> detailQuery = new QueryWrapper<>();
        detailQuery.select("id");
        detailQuery.eq("material_inspection_id",quaMaterialInspectionDTO.getId());
        quaMaterialInspectionDetailService.remove(detailQuery);

        //保存明细行
        if(CollectionUtil.isNotEmpty(quaMaterialInspectionDTO.getQuaMaterialInspectionDetailList())){
            for (QuaMaterialInspectionDetail quaMaterialInspectionDetail : quaMaterialInspectionDTO.getQuaMaterialInspectionDetailList()) {
                quaMaterialInspectionDetail.setMaterialInspectionId(quaMaterialInspectionDTO.getId());
            }
            quaMaterialInspectionDetailService.saveBatch(quaMaterialInspectionDTO.getQuaMaterialInspectionDetailList());
        }

        //删除图片
        QueryWrapper<QuaDocument> documentQuery = new QueryWrapper<>();
        documentQuery.eq("qua_id", quaMaterialInspectionDTO.getId());
        documentQuery.eq("qua_type",Const.DOCUMENT_QUA_TYPE.QUA_INSPECTION);
        documentService.remove(documentQuery);
        //保存图片
        if(CollectionUtil.isNotEmpty(quaMaterialInspectionDTO.getSysFileHisList())){
            List<QuaDocument> quaDocumentList = new ArrayList<>();
            for (SysFileHis sysFileHis : quaMaterialInspectionDTO.getSysFileHisList()) {

                QuaDocument quaDocument = new QuaDocument();
                quaDocument.setQuaId(quaMaterialInspectionDTO.getId());
                quaDocument.setDocumentId(sysFileHis.getId());
                quaDocument.setQuaType(Const.DOCUMENT_QUA_TYPE.QUA_INSPECTION);
                quaDocumentList.add(quaDocument);
            }

            documentService.saveBatch(quaDocumentList);
        }
    }

    @Override
    public void del(List<Integer> ids) {

        QueryWrapper<QuaMaterialInspection> query = new QueryWrapper<>();
        query.eq("status",1);//审核
        query.in("id",ids);
        List<QuaMaterialInspection> list = this.list(query);
        //判断是否已启用
        if(CollectionUtil.isNotEmpty(list)){
            throw new BDException("操作失败，"+list.get(0).getInspectionNo()+"已检验无法删除！");
        }

        this.removeByIds(ids);
    }

    @Override
    public QuaMaterialInspectionDTO getQuaMaterialInspection(Integer id) {
        QuaMaterialInspectionDTO quaMaterialInspectionDTO = this.baseMapper.getInfoById(id);
        if(quaMaterialInspectionDTO == null){
            throw new BDException("数据异常，请联系管理员！");
        }
        //获取明细
        List<QuaMaterialInspectionDetail> quaMaterialInspectionDetails = quaMaterialInspectionDetailService.findListByParam(id);
        quaMaterialInspectionDTO.setQuaMaterialInspectionDetailList(quaMaterialInspectionDetails);
        //照片列表
        QueryWrapper queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.select("document_id");
        queryWrapper2.eq("qua_id",id);
        queryWrapper2.eq("qua_type", Const.DOCUMENT_QUA_TYPE.QUA_INSPECTION);
        List<QuaDocument> documentList2 = documentService.list(queryWrapper2);
        // 图片列表
        if(CollectionUtil.isNotEmpty(documentList2)){
            List<Integer> fileIds = documentList2.stream()
                    .map(QuaDocument::getDocumentId)
                    .collect(Collectors.toList());
            QueryWrapper queryFileWrapper = new QueryWrapper<>();
            queryFileWrapper.in("id",fileIds);
            List<SysFileHis> fileHisList = sysFileHisService.list(queryFileWrapper);
            quaMaterialInspectionDTO.setSysFileHisList(fileHisList);
        }
        return quaMaterialInspectionDTO;
    }

    @Override
    public void audit(List<Integer> ids) {
        //UpdateWrapper<QuaMaterialInspection> quaMaterialInspectionUpdateWrapper = new UpdateWrapper<>();
        //quaMaterialInspectionUpdateWrapper.set("status",1);//审核
        //quaMaterialInspectionUpdateWrapper.set("auditor", TokenUtil.getUserId());//设置审核人
        //quaMaterialInspectionUpdateWrapper.in("id",ids);
        //quaMaterialInspectionUpdateWrapper.eq("do_delete",0);
        //this.update(quaMaterialInspectionUpdateWrapper);
    }

    @Override
    public void deAudit(List<Integer> ids) {
        //UpdateWrapper<QuaMaterialInspection> quaMaterialInspectionUpdateWrapper = new UpdateWrapper<>();
        //quaMaterialInspectionUpdateWrapper.set("status",0);//审核
        //quaMaterialInspectionUpdateWrapper.set("auditor", TokenUtil.getUserId());//设置审核人
        //quaMaterialInspectionUpdateWrapper.in("id",ids);
        //quaMaterialInspectionUpdateWrapper.eq("do_delete",0);
        //this.update(quaMaterialInspectionUpdateWrapper);
    }

    @Override
    public void firstSampleInspection(Integer dispatchId,Integer firstInspectionType) {
        // 生成首样检验编号
        String code = sysDocumentNumService.getSysDocumentNumByDocumentId(Const.DOCUMENT_ID.SYS_SYJY_DOCUMENT);
        sysDocumentNumService.incrementLastSerialByDocumentId(Const.DOCUMENT_ID.SYS_SYJY_DOCUMENT);
        //判断编号否重复
        QueryWrapper<QuaMaterialInspection> codeQuery = new QueryWrapper<>();
        codeQuery.select("id");
        codeQuery.eq("inspection_no",code);
        List codes = this.list(codeQuery);
        if(CollectionUtil.isNotEmpty(codes)) {
            throw new BDException("操作失败，检验单编号重复，请重试！");
        }
        // 获取派工单
        MesDispatch mesDispatch = mesDispatchService.getById(dispatchId);

        // 获取工序计划工序
        MesProcessPlanDetail mesProcessPlanDetail = mesProcessPlanDetailService.getById(mesDispatch.getProcessPlanDetailId());
        // 工序计划明细
        MesProcessPlanDTO mesProcessPlan = mesProcessPlanService.getInfoById(mesProcessPlanDetail.getProcessPlanId());
        // 物料
        SysMaterial material = sysMaterialService.getById(mesProcessPlan.getMaterialId());

        QuaMaterialInspection quaMaterialInspection = new QuaMaterialInspection();
        quaMaterialInspection.setFirstInspectionType(firstInspectionType);
        quaMaterialInspection.setProcessName(mesProcessPlanDetail.getProcessName());
        quaMaterialInspection.setPlanNumber(mesProcessPlan.getPlanNum());
        quaMaterialInspection.setInspectionNo(code);
        quaMaterialInspection.setSourceId(mesProcessPlan.getId());
        quaMaterialInspection.setSourceType(Const.DOCUMENT_ID.MES_PROCESS_PLAN_DOCUMENT);
        quaMaterialInspection.setMaterialId(mesProcessPlan.getMaterialId());
        quaMaterialInspection.setBatchNo(mesProcessPlan.getBatchNo());
        quaMaterialInspection.setClientId(mesProcessPlan.getClientId());
        quaMaterialInspection.setConvCoefficient(mesProcessPlan.getConvCoefficient());
        quaMaterialInspection.setDeptId(mesProcessPlan.getDeptId());
        quaMaterialInspection.setInspectionType(Const.QUA_TYPE.QUA_SYJY);
        quaMaterialInspection.setSourceNo(mesProcessPlan.getProducePlanNo());
        quaMaterialInspection.setSupplierId(material.getSupplierId());
        quaMaterialInspection.setSupportUom(material.getViceUnit());
        ///根据检验类型和物料id 货物检验项目
        List<Integer> checkPlanIds = this.baseMapper.getCheckPlanIdByMaterialId(material.getId(),Const.QUA_TYPE.QUA_SYJY);
        if(CollectionUtil.isNotEmpty(checkPlanIds)){
            quaMaterialInspection.setInspectionScheme(checkPlanIds.get(0));
        }

        MesFlowCardRuleRecord mesFlowCardRuleRecord = flowCardRuleRecordService.detail(Const.RuleType.PROCESS_PRINT,mesProcessPlan.getId());
        if(mesFlowCardRuleRecord!=null){
            quaMaterialInspection.setSendCount(mesFlowCardRuleRecord.getFirstQty());
            quaMaterialInspection.setInspectionCount(mesFlowCardRuleRecord.getFirstQty());
        }

        // 保存检验主体
        save(quaMaterialInspection);

        if(CollectionUtil.isNotEmpty(checkPlanIds)){
            saveDetails(quaMaterialInspection.getId(),checkPlanIds.get(0));
        }
    }



    @Override
    public void produceInspection(Integer processDetailId) {
        // 生成产品检验编号
        String code = sysDocumentNumService.getSysDocumentNumByDocumentId(Const.DOCUMENT_ID.QUA_CPJY_DOCUMENT);
        sysDocumentNumService.incrementLastSerialByDocumentId(Const.DOCUMENT_ID.QUA_CPJY_DOCUMENT);
        //判断编号否重复
        QueryWrapper<QuaMaterialInspection> codeQuery = new QueryWrapper<>();
        codeQuery.select("id");
        codeQuery.eq("inspection_no",code);
        List codes = this.list(codeQuery);
        if(CollectionUtil.isNotEmpty(codes)) {
            throw new BDException("操作失败，检验单编号重复，请重试！");
        }
        // 获取工序计划工序
        MesProcessPlanDetail mesProcessPlanDetail = mesProcessPlanDetailService.getById(processDetailId);
        // 工序计划明细
        MesProcessPlanDTO mesProcessPlan = mesProcessPlanService.getInfoById(mesProcessPlanDetail.getProcessPlanId());
        // 物料
        SysMaterial material = sysMaterialService.getById(mesProcessPlan.getMaterialId());

        QuaMaterialInspection quaMaterialInspection = new QuaMaterialInspection();
        quaMaterialInspection.setProcessName(mesProcessPlanDetail.getProcessName());
        quaMaterialInspection.setPlanNumber(mesProcessPlan.getPlanNum());
        quaMaterialInspection.setInspectionNo(code);
        quaMaterialInspection.setSourceId(mesProcessPlan.getId());
        quaMaterialInspection.setSourceType(Const.DOCUMENT_ID.MES_PROCESS_PLAN_DOCUMENT);
        quaMaterialInspection.setMaterialId(mesProcessPlan.getMaterialId());
        quaMaterialInspection.setBatchNo(mesProcessPlan.getBatchNo());
        quaMaterialInspection.setClientId(mesProcessPlan.getClientId());
        quaMaterialInspection.setConvCoefficient(mesProcessPlan.getConvCoefficient());
        quaMaterialInspection.setDeptId(mesProcessPlan.getDeptId());
        quaMaterialInspection.setInspectionType(Const.QUA_TYPE.QUA_CPJY);
        quaMaterialInspection.setSourceNo(mesProcessPlan.getProducePlanNo());
        quaMaterialInspection.setSupplierId(material.getSupplierId());
        quaMaterialInspection.setSupportUom(material.getViceUnit());

        //根据检验类型和物料id 货物检验项目
        List<Integer> checkPlanIds = this.baseMapper.getCheckPlanIdByMaterialId(material.getId(),Const.QUA_TYPE.QUA_CPJY);
        if(CollectionUtil.isNotEmpty(checkPlanIds)){
            quaMaterialInspection.setInspectionScheme(checkPlanIds.get(0));
        }
        // 保存检验主体
        save(quaMaterialInspection);
        if(CollectionUtil.isNotEmpty(checkPlanIds)){
            saveDetails(quaMaterialInspection.getId(),checkPlanIds.get(0));
        }
    }

    private void saveDetails(Integer inspectionId,Integer inspectionScheme){
        // 保存检验项
        //根据检验方案获取检验项目
        List<QuaMaterialInspectionDetail> quaMaterialInspectionDetails = new ArrayList<>();
        // 组装检验方案列表
        List<QuaPlanCheckRef> planCheckRefList  = planCheckRefService.list(new QueryWrapper<QuaPlanCheckRef>().eq("plan_id", inspectionScheme));
        Map<Integer, QuaPlanCheckRef> checkRefMap = planCheckRefList.stream().collect(Collectors.toMap(item -> item.getCheckId(), o -> o, (v1, v2) -> v1));

        List<Integer> fileRefIds = planCheckRefList.stream().map(QuaPlanCheckRef::getCheckId).collect(Collectors.toList());
        if (planCheckRefList.size() > 0) {
            List<QuaCheckItem> checkItemList = quaCheckItemService.listByIds(fileRefIds);
            for (QuaCheckItem quaCheckItem : checkItemList) {
                QuaPlanCheckRef ref = checkRefMap.get(quaCheckItem.getId());
                QuaMaterialInspectionDetail inspectionDetail = new QuaMaterialInspectionDetail();
                inspectionDetail.setMaterialInspectionId(inspectionId);
                inspectionDetail.setProjectId(quaCheckItem.getId());
                inspectionDetail.setProjectCode(quaCheckItem.getCheckItemCode());
                inspectionDetail.setProjectName(quaCheckItem.getCheckItemName());
                inspectionDetail.setProjectMethod(quaCheckItem.getCheckMethod());
                inspectionDetail.setUnit(ref.getGoatUnit());
                inspectionDetail.setTargetValue(ref.getGoatValue());
                inspectionDetail.setNorm(quaCheckItem.getStandardValue());
                inspectionDetail.setRemarks(quaCheckItem.getRemark());
                quaMaterialInspectionDetails.add(inspectionDetail);
            }

        }
        quaMaterialInspectionDetailService.saveBatch(quaMaterialInspectionDetails);
    }

    @Override
    public SysCountDTO inspection(){
        SysCountDTO result = new SysCountDTO();
        result.setName1("质量异常");
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.gt("unqualified_count_support",0);
        result.setValue1(String.valueOf(this.count(queryWrapper)));

        result.setName2("一次合格率");
        QueryWrapper queryWrapper2 = new QueryWrapper();
        queryWrapper2.select("SUM(qualified_count_support)/SUM(inspection_count_support) as rate");
        BigDecimal r = (BigDecimal) this.getMap(queryWrapper2).get("rate");
        result.setValue2((r.multiply(BigDecimal.valueOf(100)).setScale(0,BigDecimal.ROUND_HALF_UP)).toString()+"%");
        return result;
    }
}